package com.cgy.utils.base.reflect.stream;

import com.cgy.utils.base.list.ListHelper;
import com.cgy.utils.base.objects.ObjectHelper;
import com.cgy.utils.base.strings.StringHelper;
import com.google.common.base.Splitter;
import javassist.*;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.util.List;

/**
 * 流式操作
 * @author CH
 */
@Slf4j
public class ReflectMakeStreamBuilder {

    private String interfaceName;
    private String className;
    private StringBuffer fields = new StringBuffer(",");
    private StringBuffer methods = new StringBuffer(",");
    private String filePath;

    /**
     * 设置className
     * @param className
     * @return
     */
    public ReflectMakeStreamBuilder setClassName(final String className) {
        this.className = className;
        return this;
    }
    /**
     * 设置方法
     * @param methodExpress
     * @return
     */
    public ReflectMakeStreamBuilder setMethods(final String methodExpress) {
        this.methods.append(methodExpress).append(",");
        return this;
    }
    /**
     * 设置字段
     * @param fieldExpress
     * @return
     */
    public ReflectMakeStreamBuilder setFields(final String fieldExpress) {
        this.fields.append(fieldExpress).append(",");
        return this;
    }
    /**
     * 设置字段
     * @param interfaceName
     * @return
     */
    public ReflectMakeStreamBuilder setInterface(final String interfaceName) {
        this.interfaceName = interfaceName;
        return this;
    }
    /**
     * 设置字段
     * @param filePath
     * @return
     */
    public ReflectMakeStreamBuilder setFile(final String filePath) {
        this.filePath = filePath;
        return this;
    }

    /**
     * 构建
     */
    public void build() {
        CtClass ctClass = ObjectHelper.isAnyNotBlank(new ObjectHelper.AnyEmptyHandler<CtClass>() {
            @Override
            public CtClass handler(int size, String... value) {
                ClassPool classPool = ClassPool.getDefault();
                CtClass ctClass = classPool.makeClass(value[0]);
                String fields = value[1];
                List<String> stringFields = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(fields);
                ListHelper.iterator(stringFields, new ListHelper.IteratorHandlerEmpty<String>() {
                    @Override
                    public void next(String s) {
                        try {
                            ctClass.addField(CtField.make(s, ctClass));
                        } catch (CannotCompileException e) {
                            log.warn("{}无法创建", s);
                        }
                    }
                });
                String methods = value[2];
                List<String> stringMethodss = Splitter.on(",").trimResults().omitEmptyStrings().splitToList(methods);
                ListHelper.iterator(stringFields, new ListHelper.IteratorHandlerEmpty<String>() {
                    @Override
                    public void next(String s) {
                        try {
                            ctClass.addMethod(CtMethod.make(s, ctClass));
                        } catch (CannotCompileException e) {
                            log.warn("{}无法创建", s);
                        }
                    }
                });

                return ctClass;
            }
        }, this.className, this.fields.substring(1).toString(), this.methods.substring(1).toString());

        StringHelper.isNotBlank(interfaceName, new StringHelper.StringIfNotBlankHandler() {
            @Override
            public void handler(String value) {
                ClassPool classPool = ClassPool.getDefault();
                try {
                    CtClass ctClass1 = classPool.get(value);
                    ctClass.addInterface(ctClass1);
                } catch (NotFoundException e) {
                    log.warn("{} interface is not exist", value);
                }
            }
        });

        if(StringHelper.isNotBlank(filePath)) {
            try {
                ctClass.writeFile(filePath);
            } catch (CannotCompileException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            try {
                ctClass.writeFile();
            } catch (NotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (CannotCompileException e) {
                e.printStackTrace();
            }
        }

    }
}
